package EurekaProcessor;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Vector;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import Config.Configure;
import Config.GlobalLog;
import EurekaAnalyzer.IDInformation;
import Statistics.IDGraph;
import Statistics.IDGraphGlobalProperty;
import Statistics.IDGraphToJungGraph;
import Store.StoreManager;

/**
 * @author Xenophon
 * This is the main controller of all processors. It creates,invokes and 
 * schedules them to cooperate to finish the data processing procedure which
 * can be divided several steps. 
 *
 */
@Deprecated
public class PipelineMgr {
	private String dataDirectory;
	private int  RAW_DATA_THRESHOLD;
	
	private PreProcessor      preProcessor;
	private RawDataAnalyzer   rawDataAnalyzer;
	private IDExtractor       idExtractor;
	private StoreManager      storeMgr;
	
	private Vector<RawDataFromPage> rawDataPool;
	private HashMap<String, IDInformation> idInfoPool;
	
	private boolean isAnanlyzerStopped;
	private boolean isExtractorWaited;
	
	private Lock rawDataLock;
	private Condition enoughRawData;
	
	private Lock extractorFinishLock;
	private Condition waitExtractorFinished;
	
	public PipelineMgr(String configfile)
	{
		Configure.SetConfigureFile(configfile);
		try {
			Configure.GetConfigure();
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			GlobalLog.StartLog();
		} catch (Exception e) {
			e.printStackTrace();
		}
		RAW_DATA_THRESHOLD = Configure.RAWDATA_THRESHOLD;
		dataDirectory = Configure.ANALYZER_DIR;
		
		rawDataPool = new Vector<RawDataFromPage>();
		idInfoPool  = new HashMap<String, IDInformation>();
		isAnanlyzerStopped = false;
		isExtractorWaited  = false;
		rawDataLock = new ReentrantLock();
		enoughRawData = rawDataLock.newCondition();
		extractorFinishLock = new ReentrantLock();
		waitExtractorFinished = extractorFinishLock.newCondition();
	}
	
	public String GetSearchDir()
	{
		return dataDirectory;
	}
	
	public IDInformation GetInformationByID(String id)
	{
		if(idInfoPool.containsKey(id))
			return idInfoPool.remove(id);
		return new IDInformation(id);
	}
	
	public void PutIDInfo(String id,IDInformation info)
	{
		idInfoPool.put(id, info);
	}
	
	public void PutNewRawData(RawDataFromPage rd)
	{
		rawDataPool.add(rd);
		WakeExtractor();
	}
	
	public boolean IsRawDataCollectionEmpty()
	{
		if(rawDataPool.size()==0)
			return true;
		return false;
	}
	
	public boolean CanExtractorQuit()
	{
		return isAnanlyzerStopped;
	}
	
	public void WaitForRawData()
	{
		rawDataLock.lock();
		try {
			isExtractorWaited = true;
			enoughRawData.await();
		} catch (InterruptedException e) {
			GlobalLog.AddLog("PipelineMgr WaitForRawData Error:"+e.getMessage());
			e.printStackTrace();
		}
		rawDataLock.unlock();
	}
	
	public RawDataFromPage GetRawData()
	{
		RawDataFromPage rd = rawDataPool.lastElement();
		rawDataPool.remove(rawDataPool.size()-1);
		return rd;
	}
	
	public synchronized void WakeExtractor()
	{
		if(rawDataPool.size()<=RAW_DATA_THRESHOLD||!isExtractorWaited)
			return;
		rawDataLock.lock();
		enoughRawData.signal();
		isExtractorWaited = false;
		rawDataLock.unlock();
	}
	
	public synchronized void RawDataAnalyzerQuit()
	{
		isAnanlyzerStopped = true;
		if(isExtractorWaited)
		{
			rawDataLock.lock();
			enoughRawData.signal();
			rawDataLock.unlock();
		}
	}
	
	public void WaitExtractorFinished()
	{
		extractorFinishLock.lock();
	    try {
			waitExtractorFinished.await();
		} catch (InterruptedException e) {
			GlobalLog.AddLog("PipelineMgr WaitExtractorFinished Error:"+e.getMessage());
			e.printStackTrace();
		}
		extractorFinishLock.unlock();
	}
	
	public void ExtractorFinished()
	{
		extractorFinishLock.lock();
		waitExtractorFinished.signal();
		extractorFinishLock.unlock();
	}
	
	public void StoreIDGraphGlobalPropertyBySeralizing(IDGraphGlobalProperty graph)
	{
		if(Configure.GLOBAL_PROPERTY_FILE_PATH==null)
			return;
		GlobalLog.AddLog("Begin seralizing IDGraph global property...");
		try {
			FileOutputStream fos   = new FileOutputStream(Configure.GLOBAL_PROPERTY_FILE_PATH);
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			oos.writeObject(graph);
			fos.close();
			oos.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		GlobalLog.AddLog("serializing done...");
	}
	
	public void Process()
	{
		if (Configure.PREPROCESSOR) {
			preProcessor = new PreProcessor();
			preProcessor.StartSearch();
		}
		
		if (Configure.ANALYZER) {
			/*
			rawDataAnalyzer = new RawDataAnalyzer(this);
			idExtractor    	= new IDExtractor(this);
			*/
			
			rawDataAnalyzer.start();
			idExtractor.start();
			
			WaitExtractorFinished();
		}
		
		storeMgr = new StoreManager();
		if (Configure.STORE_IN_DB) {
			storeMgr.SetUpIDInfoDB(Configure.DATABASE_DIR);
			storeMgr.Store(idInfoPool);
		}
		
		IDGraph graph = new IDGraph(idInfoPool);
		if (Configure.STORE_GRAPH_IN_DB)
		{	
			storeMgr.SetUpGraphDatabase(Configure.GRAPH_DB_DIR);
			storeMgr.StoreGraph(graph);
		}
		
		if(Configure.STORE_GRAPH_IN_PAJEK)
		{
			IDGraphToJungGraph.StoreIDGraphInPajekFormat(graph);
		}
		
		if(Configure.STORE_GLOBAL_PROPERTY)
		{
			IDGraphGlobalProperty property = new IDGraphGlobalProperty(graph,null);
			StoreIDGraphGlobalPropertyBySeralizing(property);
		}
		
		GlobalLog.CloseLog();
	}
	
	public IDInformation GetIDInformationByID(String id)
	{
		if (idInfoPool.containsKey(id)) {
			return idInfoPool.get(id);
		}
		return null;
	}
} 
